summaryrefslogtreecommitdiffstats
path: root/src/common/settings.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/common/settings.h')
-rw-r--r--src/common/settings.h513
1 files changed, 42 insertions, 471 deletions
diff --git a/src/common/settings.h b/src/common/settings.h
index ec0686120..e03233eaf 100644
--- a/src/common/settings.h
+++ b/src/common/settings.h
@@ -5,54 +5,21 @@
#include <algorithm>
#include <array>
-#include <forward_list>
-#include <functional>
#include <map>
-#include <optional>
+#include <memory>
#include <stdexcept>
#include <string>
-#include <typeindex>
-#include <typeinfo>
#include <utility>
#include <vector>
#include "common/common_types.h"
+#include "common/settings_common.h"
#include "common/settings_enums.h"
#include "common/settings_input.h"
+#include "common/settings_setting.h"
namespace Settings {
-enum class Category : u32 {
- Audio,
- Core,
- Cpu,
- CpuDebug,
- CpuUnsafe,
- Renderer,
- RendererAdvanced,
- RendererDebug,
- System,
- SystemAudio,
- DataStorage,
- Debugging,
- DebuggingGraphics,
- Miscellaneous,
- Network,
- WebService,
- AddOns,
- Controls,
- Ui,
- UiGeneral,
- UiLayout,
- UiGameList,
- Screenshots,
- Shortcuts,
- Multiplayer,
- Services,
- Paths,
- MaxEnum,
-};
-
const char* TranslateCategory(Settings::Category category);
struct ResolutionScalingInfo {
@@ -78,441 +45,45 @@ struct ResolutionScalingInfo {
}
};
-class BasicSetting {
-protected:
- explicit BasicSetting() = default;
-
-public:
- virtual ~BasicSetting() = default;
-
- virtual Category Category() const = 0;
- virtual constexpr bool Switchable() const = 0;
- virtual std::string ToString() const = 0;
- virtual std::string ToStringGlobal() const {
- return {};
- }
- virtual void LoadString(const std::string& load) = 0;
- virtual std::string Canonicalize() const = 0;
- virtual const std::string& GetLabel() const = 0;
- virtual std::string DefaultToString() const = 0;
- virtual bool Save() const = 0;
- virtual std::type_index TypeId() const = 0;
- virtual constexpr bool IsEnum() const = 0;
- virtual bool RuntimeModfiable() const = 0;
- virtual void SetGlobal(bool global) {}
- virtual constexpr u32 Id() const = 0;
- virtual std::string MinVal() const = 0;
- virtual std::string MaxVal() const = 0;
- virtual bool UsingGlobal() const {
- return true;
- }
-};
-
-class Linkage {
-public:
- explicit Linkage(u32 initial_count = 0);
- ~Linkage();
- std::map<Category, std::forward_list<BasicSetting*>> by_category{};
- std::vector<std::function<void()>> restore_functions{};
- u32 count;
-};
-
-/** The Setting class is a simple resource manager. It defines a label and default value
- * alongside the actual value of the setting for simpler and less-error prone use with frontend
- * configurations. Specifying a default value and label is required. A minimum and maximum range
- * can be specified for sanitization.
- */
-template <typename Type, bool ranged = false>
-class Setting : public BasicSetting {
-protected:
- Setting() = default;
-
- /**
- * Only sets the setting to the given initializer, leaving the other members to their default
- * initializers.
- *
- * @param global_val Initial value of the setting
- */
- explicit Setting(const Type& val) : value{val} {}
-
-public:
- /**
- * Sets a default value, label, and setting value.
- *
- * @param linkage Setting registry
- * @param default_val Initial value of the setting, and default value of the setting
- * @param name Label for the setting
- * @param category_ Category of the setting AKA INI group
- */
- explicit Setting(Linkage& linkage, const Type& default_val, const std::string& name,
- enum Category category_, bool save_ = true, bool runtime_modifiable_ = false)
- requires(!ranged)
- : value{default_val}, default_value{default_val}, label{name}, category{category_},
- id{linkage.count}, save{save_}, runtime_modifiable{runtime_modifiable_} {
- linkage.by_category[category].push_front(this);
- linkage.count++;
- }
- virtual ~Setting() = default;
-
- /**
- * Sets a default value, minimum value, maximum value, and label.
- *
- * @param linkage Setting registry
- * @param default_val Initial value of the setting, and default value of the setting
- * @param min_val Sets the minimum allowed value of the setting
- * @param max_val Sets the maximum allowed value of the setting
- * @param name Label for the setting
- * @param category_ Category of the setting AKA INI group
- */
- explicit Setting(Linkage& linkage, const Type& default_val, const Type& min_val,
- const Type& max_val, const std::string& name, enum Category category_,
- bool save_ = true, bool runtime_modifiable_ = false)
- requires(ranged)
- : value{default_val}, default_value{default_val}, maximum{max_val}, minimum{min_val},
- label{name}, category{category_}, id{linkage.count}, save{save_},
- runtime_modifiable{runtime_modifiable_} {
- linkage.by_category[category].push_front(this);
- linkage.count++;
- }
-
- /**
- * Returns a reference to the setting's value.
- *
- * @returns A reference to the setting
- */
- [[nodiscard]] virtual const Type& GetValue() const {
- return value;
- }
-
- /**
- * Sets the setting to the given value.
- *
- * @param val The desired value
- */
- virtual void SetValue(const Type& val) {
- Type temp{ranged ? std::clamp(val, minimum, maximum) : val};
- std::swap(value, temp);
- }
-
- /**
- * Returns the value that this setting was created with.
- *
- * @returns A reference to the default value
- */
- [[nodiscard]] const Type& GetDefault() const {
- return default_value;
- }
-
- /**
- * Returns the label this setting was created with.
- *
- * @returns A reference to the label
- */
- [[nodiscard]] const std::string& GetLabel() const override {
- return label;
- }
-
- /**
- * Returns the setting's category AKA INI group.
- *
- * @returns The setting's category
- */
- [[nodiscard]] enum Category Category() const override {
- return category;
- }
-
- [[nodiscard]] bool RuntimeModfiable() const override {
- return runtime_modifiable;
- }
-
- [[nodiscard]] constexpr bool IsEnum() const override {
- return std::is_enum<Type>::value;
- }
-
- /**
- * Returns whether the current setting is Switchable.
- *
- * @returns If the setting is a SwitchableSetting
- */
- [[nodiscard]] virtual constexpr bool Switchable() const override {
- return false;
- }
-
-protected:
- std::string ToString(const Type& value_) const {
- if constexpr (std::is_same<Type, std::string>()) {
- return value_;
- } else if constexpr (std::is_same<Type, std::optional<u32>>()) {
- return value_.has_value() ? std::to_string(*value_) : "none";
- } else if constexpr (std::is_same<Type, bool>()) {
- return value_ ? "true" : "false";
- } else if (std::is_same<Type, AudioEngine>()) {
- return CanonicalizeEnum(value_);
- } else {
- return std::to_string(static_cast<u64>(value_));
- }
- }
-
-public:
- /**
- * Converts the value of the setting to a std::string. Respects the global state if the setting
- * has one.
- *
- * @returns The current setting as a std::string
- */
- std::string ToString() const override {
- return ToString(this->GetValue());
- }
-
- /**
- * Returns the default value of the setting as a std::string.
- *
- * @returns The default value as a string.
- */
- std::string DefaultToString() const override {
- return ToString(default_value);
- }
-
- /**
- * Assigns a value to the setting.
- *
- * @param val The desired setting value
- *
- * @returns A reference to the setting
- */
- virtual const Type& operator=(const Type& val) {
- Type temp{ranged ? std::clamp(val, minimum, maximum) : val};
- std::swap(value, temp);
- return value;
- }
-
- /**
- * Returns a reference to the setting.
- *
- * @returns A reference to the setting
- */
- explicit virtual operator const Type&() const {
- return value;
- }
-
- /**
- * Converts the given value to the Setting's type of value. Uses SetValue to enter the setting,
- * thus respecting its constraints.
- *
- * @param input The desired value
- */
- void LoadString(const std::string& input) override {
- if (input.empty()) {
- this->SetValue(this->GetDefault());
- return;
- }
- try {
- if constexpr (std::is_same<Type, std::string>()) {
- this->SetValue(input);
- } else if constexpr (std::is_same<Type, std::optional<u32>>()) {
- this->SetValue(static_cast<u32>(std::stoul(input)));
- } else if constexpr (std::is_same<Type, bool>()) {
- this->SetValue(input == "true");
- } else if constexpr (std::is_same<Type, AudioEngine>()) {
- this->SetValue(ToEnum<Type>(input));
- } else {
- this->SetValue(static_cast<Type>(std::stoll(input)));
- }
- } catch (std::invalid_argument) {
- this->SetValue(this->GetDefault());
- }
- }
-
- [[nodiscard]] std::string constexpr Canonicalize() const override {
- if constexpr (std::is_enum<Type>::value) {
- return CanonicalizeEnum(this->GetValue());
- }
- return ToString(this->GetValue());
- }
-
- /**
- * Returns the save preference of the setting i.e. when saving or reading the setting from a
- * frontend, whether this setting should be skipped.
- *
- * @returns The save preference
- */
- virtual bool Save() const override {
- return save;
- }
-
- /**
- * Gives us another way to identify the setting without having to go through a string.
- *
- * @returns the type_index of the setting's type
- */
- virtual std::type_index TypeId() const override {
- return std::type_index(typeid(Type));
- }
-
- virtual constexpr u32 Id() const override {
- return id;
- }
-
- virtual std::string MinVal() const override {
- return this->ToString(minimum);
- }
- virtual std::string MaxVal() const override {
- return this->ToString(maximum);
- }
-
-protected:
- Type value{}; ///< The setting
- const Type default_value{}; ///< The default value
- const Type maximum{}; ///< Maximum allowed value of the setting
- const Type minimum{}; ///< Minimum allowed value of the setting
- const std::string label{}; ///< The setting's label
- const enum Category category; ///< The setting's category AKA INI group
- const u32 id;
- bool save;
- bool runtime_modifiable;
-};
-
-/**
- * The SwitchableSetting class is a slightly more complex version of the Setting class. This adds a
- * custom setting to switch to when a guest application specifically requires it. The effect is that
- * other components of the emulator can access the setting's intended value without any need for the
- * component to ask whether the custom or global setting is needed at the moment.
- *
- * By default, the global setting is used.
- */
-template <typename Type, bool ranged = false>
-class SwitchableSetting : virtual public Setting<Type, ranged> {
-public:
- /**
- * Sets a default value, label, and setting value.
- *
- * @param linkage Setting registry
- * @param default_val Initial value of the setting, and default value of the setting
- * @param name Label for the setting
- * @param category_ Category of the setting AKA INI group
- */
- explicit SwitchableSetting(Linkage& linkage, const Type& default_val, const std::string& name,
- Category category, bool save = true, bool runtime_modifiable = false)
- requires(!ranged)
- : Setting<Type, false>{linkage, default_val, name, category, save, runtime_modifiable} {
- linkage.restore_functions.emplace_back([this]() { this->SetGlobal(true); });
- }
- virtual ~SwitchableSetting() = default;
-
- /**
- * Sets a default value, minimum value, maximum value, and label.
- *
- * @param linkage Setting registry
- * @param default_val Initial value of the setting, and default value of the setting
- * @param min_val Sets the minimum allowed value of the setting
- * @param max_val Sets the maximum allowed value of the setting
- * @param name Label for the setting
- * @param category_ Category of the setting AKA INI group
- */
- explicit SwitchableSetting(Linkage& linkage, const Type& default_val, const Type& min_val,
- const Type& max_val, const std::string& name, Category category,
- bool save = true, bool runtime_modifiable = false)
- requires(ranged)
- : Setting<Type, true>{linkage, default_val, min_val, max_val,
- name, category, save, runtime_modifiable} {
- linkage.restore_functions.emplace_back([this]() { this->SetGlobal(true); });
- }
-
- /**
- * Tells this setting to represent either the global or custom setting when other member
- * functions are used.
- *
- * @param to_global Whether to use the global or custom setting.
- */
- void SetGlobal(bool to_global) override {
- use_global = to_global;
- }
-
- /**
- * Returns whether this setting is using the global setting or not.
- *
- * @returns The global state
- */
- [[nodiscard]] bool UsingGlobal() const override {
- return use_global;
- }
-
- /**
- * Returns either the global or custom setting depending on the values of this setting's global
- * state or if the global value was specifically requested.
- *
- * @param need_global Request global value regardless of setting's state; defaults to false
- *
- * @returns The required value of the setting
- */
- [[nodiscard]] virtual const Type& GetValue() const override {
- if (use_global) {
- return this->value;
- }
- return custom;
- }
- [[nodiscard]] virtual const Type& GetValue(bool need_global) const {
- if (use_global || need_global) {
- return this->value;
- }
- return custom;
- }
-
- /**
- * Sets the current setting value depending on the global state.
- *
- * @param val The new value
- */
- void SetValue(const Type& val) override {
- Type temp{ranged ? std::clamp(val, this->minimum, this->maximum) : val};
- if (use_global) {
- std::swap(this->value, temp);
- } else {
- std::swap(custom, temp);
- }
- }
-
- [[nodiscard]] virtual constexpr bool Switchable() const override {
- return true;
- }
-
- [[nodiscard]] virtual std::string ToStringGlobal() const override {
- return this->ToString(this->value);
- }
-
- /**
- * Assigns the current setting value depending on the global state.
- *
- * @param val The new value
- *
- * @returns A reference to the current setting value
- */
- const Type& operator=(const Type& val) override {
- Type temp{ranged ? std::clamp(val, this->minimum, this->maximum) : val};
- if (use_global) {
- std::swap(this->value, temp);
- return this->value;
- }
- std::swap(custom, temp);
- return custom;
- }
-
- /**
- * Returns the current setting value depending on the global state.
- *
- * @returns A reference to the current setting value
- */
- virtual explicit operator const Type&() const override {
- if (use_global) {
- return this->value;
- }
- return custom;
- }
-
-protected:
- bool use_global{true}; ///< The setting's global state
- Type custom{}; ///< The custom value of the setting
-};
+// Instantiate the classes elsewhere (settings.cpp) to reduce compiler/linker work
+#define SETTING(TYPE, RANGED) extern template class Setting<TYPE, RANGED>
+#define SWITCHABLE(TYPE, RANGED) extern template class SwitchableSetting<TYPE, RANGED>
+
+SETTING(AudioEngine, false);
+SETTING(bool, false);
+SETTING(int, false);
+SETTING(s32, false);
+SETTING(std::string, false);
+SETTING(std::string, false);
+SETTING(u16, false);
+SWITCHABLE(AnisotropyMode, true);
+SWITCHABLE(AntiAliasing, false);
+SWITCHABLE(AspectRatio, true);
+SWITCHABLE(AstcDecodeMode, true);
+SWITCHABLE(AstcRecompression, true);
+SWITCHABLE(AudioMode, true);
+SWITCHABLE(CpuAccuracy, true);
+SWITCHABLE(FullscreenMode, true);
+SWITCHABLE(GpuAccuracy, true);
+SWITCHABLE(Language, true);
+SWITCHABLE(NvdecEmulation, false);
+SWITCHABLE(Region, true);
+SWITCHABLE(RendererBackend, true);
+SWITCHABLE(ScalingFilter, false);
+SWITCHABLE(ShaderBackend, true);
+SWITCHABLE(TimeZone, true);
+SETTING(VSyncMode, true);
+SWITCHABLE(bool, false);
+SWITCHABLE(int, false);
+SWITCHABLE(int, true);
+SWITCHABLE(s64, false);
+SWITCHABLE(u16, true);
+SWITCHABLE(u32, false);
+SWITCHABLE(u8, false);
+SWITCHABLE(u8, true);
+
+#undef SETTING
+#undef SWITCHABLE
/**
* The InputSetting class allows for getting a reference to either the global or custom members.